/**
* PeriodicalUpdater - jQuery plugin for timed, decaying ajax calls
*
* http://www.360innovate.co.uk/blog/2009/03/periodicalupdater-for-jquery/
* http://enfranchisedmind.com/blog/posts/jquery-periodicalupdater-ajax-polling/
*
* Copyright (c) 2009 by the following:
* Frank White (http://customcode.info)
* Robert Fischer (http://smokejumperit.com)
* 360innovate (http://www.360innovate.co.uk)
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
* Version: 3.0
*
*/

(function($) {
    var pu_log = function(msg) {
try {
console.log(msg);
} catch(err) {}
}

// Now back to our regularly scheduled work
$.PeriodicalUpdater = function(url, options, callback){
var settings = jQuery.extend(true, {
url: url, // URL of ajax request
cache: false, // By default, don't allow caching
method: 'GET', // method; get or post
data: '', // array of values to be passed to the page - e.g. {name: "John", greeting: "hello"}
minTimeout: 1000, // starting value for the timeout in milliseconds
maxTimeout: 8000, // maximum length of time between requests
multiplier: 2, // if set to 2, timerInterval will double each time the response hasn't changed (up to maxTimeout)
          maxCalls: 0, // maximum number of calls. 0 = no limit.
          autoStop: 0 // automatically stop requests after this many returns of the same data. 0 = disabled
        }, options);

// set some initial values, then begin
var timer = null;
var timerInterval = settings.minTimeout;
        var maxCalls = settings.maxCalls;
        var autoStop = settings.autoStop;
        var calls = 0;
        var noChange = 0;

        var reset_timer = function(interval) {
          if (timer != null) {
            clearTimeout(timer);
          }
          timerInterval = interval;
pu_log('resetting timer to '+ timerInterval +'.');
          timer = setTimeout(getdata, timerInterval);
        }

// Function to boost the timer
        var boostPeriod = function() {
          if(settings.multiplier > 1) {
            before = timerInterval;
timerInterval = timerInterval * settings.multiplier;

if(timerInterval > settings.maxTimeout) {
timerInterval = settings.maxTimeout;
}
after = timerInterval;
pu_log('adjusting timer from '+ before +' to '+ after +'.');
reset_timer(timerInterval);
}
};

// Construct the settings for $.ajax based on settings
var ajaxSettings = jQuery.extend(true, {}, settings);
if(settings.type && !ajaxSettings.dataType) ajaxSettings.dataType = settings.type;
if(settings.sendData) ajaxSettings.data = settings.sendData;
ajaxSettings.type = settings.method; // 'type' is used internally for jQuery. Who knew?
ajaxSettings.ifModified = true;

// Create the function to get data
// TODO It'd be nice to do the options.data check once (a la boostPeriod)
function getdata() {
var toSend = jQuery.extend(true, {}, ajaxSettings); // jQuery screws with what you pass in
if(typeof(options.data) == 'function') {
toSend.data = options.data();
if(toSend.data) {
// Handle transformations (only strings and objects are understood)
if(typeof(toSend.data) == "number") {
toSend.data = toSend.data.toString();
}
}
}

          if(maxCalls == 0) {
            $.ajax(toSend);
          } else if(maxCalls > 0 && calls < maxCalls) {
            $.ajax(toSend);
            calls++;
          }
}

// Implement the tricky behind logic
var remoteData = null;
var prevData = null;

ajaxSettings.success = function(data) {
pu_log("Successful run! (In 'success')");
remoteData = data;
// timerInterval = settings.minTimeout;
};

ajaxSettings.complete = function(xhr, success) {
//pu_log("Status of call: " + success + " (In 'complete')");
          if(maxCalls == -1) return;
if(success == "success" || success == "notmodified") {
var rawData = $.trim(xhr.responseText);
            if(rawData == 'STOP_AJAX_CALLS') {
              maxCalls = -1;
              return;
            }
if(prevData == rawData) {
              if(autoStop > 0) {
                noChange++;
                if(noChange == autoStop) {
                  maxCalls = -1;
                  return;
                }
              }
boostPeriod();
} else {
              noChange = 0;
              reset_timer(settings.minTimeout);
prevData = rawData;
if(remoteData == null) remoteData = rawData;
              if(ajaxSettings.dataType == 'json') {
//                remoteData = JSON.parse(remoteData);
                remoteData = jQuery.parseJSON(remoteData);
              }
if(settings.success) { settings.success(remoteData, success, xhr); }
if(callback) callback(remoteData, success, xhr);
}
}
remoteData = null;
}


ajaxSettings.error = function (xhr, textStatus) {
//pu_log("Error message: " + textStatus + " (In 'error')");
if(textStatus == "notmodified") {
boostPeriod();
} else {
prevData = null;
reset_timer(settings.minTimeout);
}
if(settings.error) { settings.error(xhr, textStatus); }
};

// Make the first call
$(function() { reset_timer(timerInterval); });

        var handle = {
          stop: function() {
            maxCalls = -1;
            return;
          }
        };
        return handle;
    };
})(jQuery);